#pragma once

#include <iostream>
#include <string>
#include <functional>
#include <unistd.h>
#include "InetAddr.hpp"

class Reactor;

class Connection;
using func_t = std::function<void(Connection *)>;

class Connection
{
public:
    Connection(int sockfd)
        : _sockFd(sockfd)
    {
    }

    int SockFd()
    {
        return _sockFd;
    }

    void Register(func_t reader, func_t writer, func_t excepter)
    {
        _reader = reader;
        _writer = writer;
        _excepter = excepter;
    }

    void SetEvents(uint32_t events)
    {
        _events = events;
    }

    uint32_t Events()
    {
        return _events;
    }

    // 设置Reactor指针
    void SetSelf(Reactor* R)
    {
        _R = R;
    }

    void SetAddr(const InetAddr& addr)
    {
        _addr = addr;
    }

    std::string& Inbuffer() // 这里使用引用是为了方便处理序列化
    {
        return _inbuffer;
    }

    std::string& Outbuffer()
    {
        return _outbuffer;
    }

    bool OutbufferEmpty()
    {
        return _outbuffer.empty();
    }

    void OutbufferRmove(int n)
    {
        _outbuffer.erase(0, n);
    }

    void Close()
    {
        if (_sockFd > 0)
            ::close(_sockFd);
    }
    ~Connection()
    {
        if (_sockFd > 0)
            ::close(_sockFd);
    }

private:
    int _sockFd; // 该连接对应的文件描述符

    uint32_t _events; // fd 关心的事件

    std::string _inbuffer;  // 如果 fd 进行读事件，通过fd将内容读取到此处
    std::string _outbuffer; // 如果 fd 进行写事件，通过fd将内容此处写出


public:
    func_t _reader;   // 如果 fd 进行读事件，通过_reader将内容读取到缓冲区中
    func_t _writer;   // 如果 fd 进行写事件，通过_writer将缓冲区中的内容写出
    func_t _excepter; // 处理异常事件

    Reactor *_R; // 反指向Reactor，以便listen获取到的新连接能够添加到Reactor中
    InetAddr _addr; // 该连接对应对端客户端的信息
};
